#include "../../../include/common/tracing/tracer.h"
#include "../../../include/common/logger/logger.h"

#include <random>
#include <sstream>
#include <iomanip>
#include <curl/curl.h>
#include <nlohmann/json.hpp>

// 生成随机ID
std::string generateRandomId(int length = 16) {
    static const char hex[] = "0123456789abcdef";
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 15);
    
    std::string result;
    result.reserve(length);
    for (int i = 0; i < length; ++i) {
        result.push_back(hex[dis(gen)]);
    }
    
    return result;
}

// SpanContext 实现
SpanContext SpanContext::createRandom() {
    SpanContext ctx;
    ctx.traceId = generateRandomId(32);
    ctx.spanId = generateRandomId(16);
    ctx.parentSpanId = "";
    return ctx;
}

SpanContext SpanContext::fromHeaders(const std::map<std::string, std::string>& headers) {
    SpanContext ctx;
    
    auto traceIt = headers.find("X-Trace-ID");
    if (traceIt != headers.end()) {
        ctx.traceId = traceIt->second;
    } else {
        ctx.traceId = generateRandomId(32);
    }
    
    auto spanIt = headers.find("X-Span-ID");
    if (spanIt != headers.end()) {
        ctx.parentSpanId = spanIt->second;
    }
    
    ctx.spanId = generateRandomId(16);
    
    return ctx;
}

std::map<std::string, std::string> SpanContext::toHeaders() const {
    return {
        {"X-Trace-ID", traceId},
        {"X-Span-ID", spanId},
        {"X-Parent-Span-ID", parentSpanId}
    };
}

// Span 实现
Span::Span(const std::string& operationName, const SpanContext& context)
    : operationName_(operationName),
      context_(context),
      startTime_(std::chrono::system_clock::now()),
      finished_(false) {
}

Span::~Span() {
    if (!finished_) {
        finish();
    }
}

void Span::setTag(const std::string& key, const std::string& value) {
    if (!finished_) {
        tags_[key] = value;
    }
}

void Span::log(const std::string& event, const std::string& payload) {
    if (!finished_) {
        logs_.emplace_back(event, payload);
    }
}

void Span::finish() {
    if (!finished_) {
        endTime_ = std::chrono::system_clock::now();
        finished_ = true;
        Tracer::instance().reportSpan(*this);
    }
}

const SpanContext& Span::context() const {
    return context_;
}

// Tracer 实现
Tracer& Tracer::instance() {
    static Tracer instance;
    return instance;
}

std::shared_ptr<Span> Tracer::startSpan(const std::string& operationName, const SpanContext& parentContext) {
    SpanContext newContext;
    newContext.traceId = parentContext.traceId;
    newContext.spanId = generateRandomId(16);
    newContext.parentSpanId = parentContext.spanId;
    
    auto span = std::make_shared<Span>(operationName, newContext);
    
    {
        std::lock_guard<std::mutex> lock(mutex_);
        activeSpan_ = span;
    }
    
    return span;
}

std::shared_ptr<Span> Tracer::activeSpan() {
    std::lock_guard<std::mutex> lock(mutex_);
    return activeSpan_;
}

void Tracer::reportSpan(const Span& span) {
    if (collectorUrl_.empty()) {
        LOG_WARNING("Tracer collector URL not set, span will not be reported");
        return;
    }
    
    try {
        // 创建JSON对象表示Span
        nlohmann::json spanJson;
        spanJson["operation_name"] = span.operationName_;
        spanJson["trace_id"] = span.context_.traceId;
        spanJson["span_id"] = span.context_.spanId;
        spanJson["parent_span_id"] = span.context_.parentSpanId;
        spanJson["service_name"] = serviceName_;
        
        // 计算持续时间（微秒）
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
            span.endTime_ - span.startTime_).count();
        spanJson["duration_us"] = duration;
        
        // 格式化开始时间
        auto startTimeT = std::chrono::system_clock::to_time_t(span.startTime_);
        std::stringstream ss;
        ss << std::put_time(std::gmtime(&startTimeT), "%FT%T.") 
           << std::chrono::duration_cast<std::chrono::microseconds>(
                  span.startTime_.time_since_epoch()).count() % 1000000 << "Z";
        spanJson["start_time"] = ss.str();
        
        spanJson["tags"] = span.tags_;
        
        // 添加日志
        nlohmann::json logsJson = nlohmann::json::array();
        for (const auto& log : span.logs_) {
            logsJson.push_back({
                {"event", log.first},
                {"payload", log.second}
            });
        }
        spanJson["logs"] = logsJson;
        
        // 发送到收集器
        std::string jsonStr = spanJson.dump();
        
        // 使用CURL发送数据（异步）
        std::thread([this, jsonStr]() {
            CURL* curl = curl_easy_init();
            if (curl) {
                struct curl_slist* headers = NULL;
                headers = curl_slist_append(headers, "Content-Type: application/json");
                
                curl_easy_setopt(curl, CURLOPT_URL, collectorUrl_.c_str());
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonStr.c_str());
                curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);  // 1秒超时，避免阻塞
                
                CURLcode res = curl_easy_perform(curl);
                if (res != CURLE_OK) {
                    LOG_ERROR("Failed to send trace: " + std::string(curl_easy_strerror(res)));
                }
                
                curl_slist_free_all(headers);
                curl_easy_cleanup(curl);
            }
        }).detach();
        
    } catch (const std::exception& e) {
        LOG_ERROR("Error reporting span: " + std::string(e.what()));
    }
}

void Tracer::init(const std::string& serviceName, const std::string& collectorUrl) {
    std::lock_guard<std::mutex> lock(mutex_);
    serviceName_ = serviceName;
    collectorUrl_ = collectorUrl;
    LOG_INFO("Tracer initialized for service: " + serviceName);
} 